import java.io.*;
import java.util.Scanner;
import java.math.BigInteger;

// Within the program, all number values will be converted from hex to dec
// when they are read from the load file and will only be converted back
// into hex for output.
/**
 * Simulates execution of a CSE7000 program in two passes.<br><br>
 * @author meghan
 * Change Log:<br>
 *  - 05/23/09 - Meghan Day<br>
 *  	- Created skeleton and global variables.<br><br>
 *	- 05/24/09 - Meghan Day<br>
 *		- Removed getNextNonSeparatorToken method as there's now a SimulatorTokenizer
 *	class to do fill this function.<br>
 *		- Filled in part of pass1.<br><br>
 *	- 05/26/09 - Meghan Day<br>
 *		- Finished main.<br>
 *		- Added input and output files as args to appropriate methods.<br>
 *		- Filled in some of pass1<br><br>
 *	- 05/28/09 - Meghan Day<br>
 *		- Fixed some errors in pass1.<br>
 *		- Added loadAddress global.<br><br>
 *	- 06/01/09 - Meghan Day<br>
 *		- Filled in/fixed error reporting in pass1, main, and several execute methods.
 */
public class Simulator {
	
	/** Constant - word size in CSE7000 machine.
	 */
	private static final int WORD = 32;
	
	 /** Constant - half word size in CSE7000 machine.
	 */
	private static final int HALF_WORD = 16;
	
	/** Constant - maximum memory address in CSE7000 machine.
	 */
	private static final int MAX_MEM_ADDR = 4095;
	
	/** Constant - length of memory in CSE7000 machine.
	 */
	private static final int MEM_LEN = 4096;
	
	/** Accumulator register (32-bits).
	 */
	protected static Register acRegister = new Register(WORD);
	
	/** MQ register (32-bits).
	 */
	protected static Register mqRegister = new Register(WORD);
	
	/** Index register 1 (16-bits).
	 */
	protected static Register xr1 = new Register(HALF_WORD);
	
	/** Index register 2 (16-bits).
	 */
	protected static Register xr2 = new Register(HALF_WORD);
	
	/**  Index register 3 (16-bits).
	 */
	protected static Register xr3 = new Register(HALF_WORD);
	
	/** Index register 4 (16-bits).
	 */
	protected static Register xr4 = new Register(HALF_WORD);
	
	/** Index register 5 (16-bits). 
	 */
	protected static Register xr5 = new Register(HALF_WORD);
	
	/** Index register 6 (16-bits).
	 */
	protected static Register xr6 = new Register(HALF_WORD);
	
	/** Index register 7 (16-bits).
	 */
	protected static Register xr7 = new Register(HALF_WORD);
	
	/** Instruction register (32-bits).
	 */
	protected static Register instructionRegister = new Register(WORD);
	
	/** Location counter.
	 */
	protected static Register locationCounter = new Register(HALF_WORD);
	
	/** Memory representation.
	 */
	protected static Memory memory = new Memory(MEM_LEN, WORD);
	
	/** Module name of program being executed.
	 */
	private static String moduleName = null;
	
	/** Length of program being executed.
	 */
	private static int moduleLen = 0;
	
	/** Initial load address of the program being executed.
	 */
	private static int loadAddress = 0;
	
	/** 
	 */
	private static int mathOp1 = 0;
	
	/** 
	 */
	private static int mathOp2 = 0;
	
	/** Increment the location counter.<br><br>
	 * Change log:<br>
	 *  - 5/23/09 - Meghan Day<br>
	 *  	-Created method.
	 */
	private static void incrementLC(){
		locationCounter.setValue(locationCounter.getValue() + 1);
	}
	
	/** Execute ABS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method<br><br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked for overflow<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Fixed overflow.
	 */
	private static void executeABS(){
		if (acRegister.getValue() < 0) {
			if (acRegister.getValue() == Integer.MIN_VALUE) {
				mqRegister.setValue(1);
				acRegister.setValue(-2);
			}
			else {
				int temp = -acRegister.getValue();
				acRegister.setValue(temp);
			}
		}
		incrementLC();
	}
	
	/** Execute ARS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeARS(BufferedWriter output){
		mqRegister.setValue(0);
		if (getEffAddress() >= 0) {
			acRegister.setValue(acRegister.getValue() >>> getEffAddress());
		} else {
			try {
				output.write("Can not shift a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute BRYL instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeBYRL(BufferedWriter output) {
		mqRegister.setValue(0);
		if (getEffAddress() >= 0) {
			acRegister.setValue(Integer.rotateLeft(acRegister.getValue(), getEffAddress() * 8));
		} else {
			try {
				output.write("Cannot rotate a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute BYRR instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeBYRR(BufferedWriter output) {
		mqRegister.setValue(0);
		if (getEffAddress() >= 0) {
			acRegister.setValue(Integer.rotateRight(acRegister.getValue(), getEffAddress() * 8));
		} else {
			try {
				output.write("Can not rotate a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute ALS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Changed to accept operands greater than 32 as documented.
	 */
	private static void executeALS(BufferedWriter output) {
		mqRegister.setValue(0);
		if (getEffAddress() >= 0) {
			acRegister.setValue(acRegister.getValue() << getEffAddress());
		} else {
			try {
				output.write("Can not shift a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute LGSL instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method. <br><br>
	 * - 06/03/09 - Dan Carpenter<br>
	 * 		- corrected infinite loop
	 */
	private static void executeLGSL(BufferedWriter output) {
		int value = getEffAddress();
		if(value >= 0) {
			int bitmask = 0, count = 0;
			while (count < value) {
				bitmask += Math.pow(2, count);
				count++;
			}
			bitmask = bitmask << (32 - value);
			int tempInt = (acRegister.getValue() & bitmask) >>> (32 - value);
			mqRegister.setValue((mqRegister.getValue() << value) | tempInt);
			acRegister.setValue(acRegister.getValue() << value);
		} else {
			try {
				output.write("Can not shift a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute LGLR instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * - 06/3/09 - Dan Carpenter<br>
	 * 		- corrected infinite loop<br><br>
	 * - 06/04/09 - Meghan Day<br>
	 * 		- Allows operands greater than 64.
	 */
	private static void executeLGLR(BufferedWriter output) {
		int value = getEffAddress();
		if(value >= 0) {
			int bitmask = 0, count = 0;
			while (count < value) {
				bitmask += Math.pow(2, count);
				count++;
			}
			int tempInt = (mqRegister.getValue() & bitmask) << (32 - value);
			acRegister.setValue((acRegister.getValue() >>> value) | tempInt);
			mqRegister.setValue(mqRegister.getValue() >>> value);
		} else {
			try {
				output.write("Can not shift a negative amount.");
				output.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");
			}
		}
		incrementLC();
	}
	
	/** Execute ANA instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * - 06/04/09 - Meghan Day<br>
	 * 		- Fixed getting value of operand.
	 */
	private static void executeANA() {
		mqRegister.setValue(0);
		int value;

		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		acRegister.setValue(acRegister.getValue() & value);
		incrementLC();
		
		/*
		if (instructionRegister.getAddrFlag() == 2) {
			acRegister.setValue(acRegister.getValue() & getEffAddress());
		} else {
			acRegister.setValue(acRegister.getValue() & memory.getValue(getEffAddress()));
		}
		*/
	}

	
	/** Execute ANS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Fixed addressing in case of immediate.
	 */
	private static void executeANS() {
		mqRegister.setValue(0);
		int address, value;
		address = getEffAddress();
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(address);
		} else {	// if operand is immediate, just use the returned value
			value = address;
		}
		
		memory.setValue(address, acRegister.getValue() & value);
		incrementLC();
	}

	
	/** Execute CHS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked for overflow<br><br>
	 * - 06/04/09 - Meghan Day<br>
	 * 		- Cleared mq at the beginning.<br>
	 * 		- Fixed problem with inaccurate overflow.
	 */
	private static void executeCHS() {
		mqRegister.setValue(0);
		if (acRegister.getValue() == Integer.MIN_VALUE) {
			mqRegister.setValue(1);
			acRegister.setValue(-2);
		}
		else {
			int value = -acRegister.getValue();
			acRegister.setValue(value);
		}
		/*
		long value = -acRegister.getValue();
		acRegister.setValue((int)(value & 0xFFFFFFFF));
		mqRegister.setValue((int)(value >>> 32));
		*/
		incrementLC();
	}
	
	/** 
	 * 	Execute EORA instruction in simulator.<br><br>
	 * 	Change log:<br>
	 * 	- 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeEORA() {
		mqRegister.setValue(0);
		int value = 0;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		acRegister.setValue(acRegister.getValue() ^ value);
		incrementLC();
	}

	/** Execute LOR instruction in simulator.<br><br>
	 * 	Change log:<br>
	 *	- 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeLOR() {
		mqRegister.setValue(0);
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		acRegister.setValue(value | acRegister.getValue());
		incrementLC();
	}

	/** Execute LORS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeLORS() {
		mqRegister.setValue(0);
		int address = getEffAddress();
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(address);
		} else {	// if operand is immediate, just use the returned value
			value = address;
		}
		
		memory.setValue(address, acRegister.getValue() | value);
		incrementLC();
	}

	
	/** Execute OR instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- fixed calls to getEffAddr()
	 */
	private static void executeOR() {
		mqRegister.setValue(0);
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		acRegister.setValue(value | acRegister.getValue());
		incrementLC();
	}

	
	/** Execute ORS instruction in simulator.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.
	 */
	private static void executeORS() {
		mqRegister.setValue(0);
		int address = getEffAddress();
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(address);
		} else {	// if operand is immediate, just use the returned value
			value = address;
		}
		
		memory.setValue(address, acRegister.getValue() | value);
		incrementLC();
	}
	
	/** 
	 *  Stores the address field of ac in the address field of the specified location
	 *  in memory.<br><br>
	 * Change log:<br>
	 * - 05/30/09 - Sam Jones<br>
	 * 		- wrote method.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Rewrote method based on new interpretation of description.
	 */
	private static void executeSLW() {
		int address = getEffAddress();
		int value = memory.getValue(address);
		
		StringBuffer temp = new StringBuffer(Integer.toHexString(value));
		StringBuffer acField = new StringBuffer(Integer.toHexString(acRegister.getAddressField()));
		while (temp.length() < 8) {
			temp.insert(0, '0');
		}
		while (acField.length() < 4) {
			acField.insert(0, '0');
		}

		temp.replace(4, 8, acField.toString());
		memory.setValue(address, Integer.parseInt(temp.toString(), 16));
		
		incrementLC();	
	}
	
	/**
	 * Adds the value of ac with the value at the effective address and
	 * places it in ac.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.<br><br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked to remove mathhelp() and make more readable.<br><br>
	 * - 06/04/09 - Meghan Day<br>
	 * 		- Fixed overflow.
	 * @author Ben Tarney
	 */
	private static void executeADD(BufferedWriter outputFile){
		mqRegister.setValue(0);
		long value = 0;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		value += acRegister.getValue();	// add the value of the ac
		
		// if overflow is going to occur, set the mq to overflow
		if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
			long mqValue = (int) Long.rotateRight(value, 32);
			value = (int) value;
			
			if (mqValue == 0){
				mqRegister.setValue(1);
			}
			else {
				mqRegister.setValue((int) mqValue);
			}
			acRegister.setValue((int) value);
		}
		else {
			acRegister.setValue((int)value);
		}
		incrementLC();

		/*
		StringBuffer mqacStr = new StringBuffer(Long.toBinaryString(value));
		while(mqacStr.length() < 64){
			mqacStr.insert(0, 0);
		}
		//String temp = mqacStr.toString();
		//String acStr = temp.substring(32,64);
		//String mqStr = temp.substring(0,31);
		//acRegister.setValue(Integer.parseInt(acStr,2));
		//mqRegister.setValue(Integer.parseInt(mqStr,2));

		acRegister.setValue((int)(value & 0xFFFFFFFF));
		mqRegister.setValue((int)(value >>> 32));
		*/
	}
	
	
	/**
	 * Subtracts the value at the effective address from the value of
	 * ac and places it in ac.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.<br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked to remove mathhelp() and make more readable.
	 * @author Ben Tarney
	 */
	private static void executeSUB(BufferedWriter outputFile){
		mqRegister.setValue(0);
		long value = 0;
		
		if (instructionRegister.getAddrFlag() != 2) {
			value = acRegister.getValue() - memory.getValue(getEffAddress());
		} else {
			value = acRegister.getValue() - getEffAddress();
		}
		
		if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
			long mqValue = (int) Long.rotateRight(value, 32);
			value = (int) value;

			if (mqValue == 0){
				mqRegister.setValue(1);
			}
			else {
				mqRegister.setValue((int) mqValue);
			}
		}
		else {
			acRegister.setValue((int)value);
		}
		
		incrementLC();
	}
	
	/**
	 * 	Value of AC is raised to power of addr field.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 05/30/09 - Ben Tarney<br>
	 * 		- Filled in method.<br><br>
	 * 	- 05/31/09 - Ben Tarney<br>
	 * 		- added check to see if power is too big.<br><br>
	 * 	- 06/04/09 - Ben Tarney	<br>
	 * 		- changed way value is stored in ac/mq<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Added check to see if power is less than 0.
	 * @author Ben Tarney
	 */
	private static void executePWR(BufferedWriter outputFile){
		mqRegister.setValue(0);
		if((instructionRegister.getAddressField() >= 0) && (instructionRegister.getAddressField() <= 10)){
			long value = (long) Math.pow(acRegister.getValue(), instructionRegister.getAddressField());
			
			if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
				long mqValue = (int) Long.rotateRight(value, 32);
				value = (int) value;

				if (mqValue == 0){
					mqRegister.setValue(1);
				}
				else {
					mqRegister.setValue((int) mqValue);
				}
			}
			acRegister.setValue((int)value);
		}
		else{
			try {
				outputFile.write("Error: Highest power a number can be raised to is 10.");
				outputFile.newLine();
			} catch (IOException e) {
				System.out.println("Cannot write to file.");			}
		}
	incrementLC();
	}
	
	/**
	 * MOD value of ac with addr field and places it in ac.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.
	 * @author Ben Tarney
	 */
	private static void executeMOD(){
		mqRegister.setValue(0);
		acRegister.setValue(acRegister.getValue() % instructionRegister.getAddressField());
		incrementLC();
	}
	
	/**
	 * MOD value of mq with addr field and places it in mq.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method
	 * @author Ben Tarney
	 */
	private static void executeMODQ(){
		mqRegister.setValue(mqRegister.getValue() % instructionRegister.getAddressField());
		incrementLC();
	}
	
	/**
	 * Decreases the value of index register 1 by one.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 5/30/09 - Ben Tarney<br>
	 * 		- Filled in method.<br><br>
	 * 	- 06/02/09 - Meghan Day<br>
	 * 		- Fixed method, as was implemented to fit old version of method.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Only decrements if the current value of xr1 is greater than min short.
	 * @author Ben Tarney
	 */
	private static void executeDRXR(BufferedWriter outputFile){
		if (xr1.getValue() > Short.MIN_VALUE) {
			xr1.setValue(xr1.getValue() - 1);
		}
		incrementLC();
	}
	
	/**
	 * 	Increases the value of index register 1 by one.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 05/30/09 - Ben Tarney<br>
	 * 		- Filled in method.<br><br>
	 * 	- 06/02/09 - Ben Tarney<br>
	 * 		- Fixed it so it only changes index register 1.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Fixed so it doesn't increment if xr1 is max value.
	 * @author Ben Tarney
	 */
	private static void executeINCXR(BufferedWriter outputFile){
		if (xr1.getValue() != Short.MAX_VALUE) {
			xr1.setValue(xr1.getValue() + 1);
		}
		incrementLC();
	}
	
	/**
	 * Sets all registers to zero.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.
	 * @author Ben Tarney
	 */
	private static void executeSARZ(){
		xr1.setValue(0);
		xr2.setValue(0);
		xr3.setValue(0);
		xr4.setValue(0);
		xr5.setValue(0);
		xr6.setValue(0);
		xr7.setValue(0);
		acRegister.setValue(0);
		mqRegister.setValue(0);
		incrementLC();
	}
	
	/**
	 * Calls external routine with the address of the parameter list already
	 * set in XR1.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.<br><br>
	 * -5/31/09 - Ben Tarney<br>
	 * 		- Finished Method.
	 * @author Ben Tarney
	 */
	private static void executeCALL(){
		locationCounter.setValue(instructionRegister.getAddressField());
	}
	
	/**
	 * Increases LC does nothing else.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.
	 * @author Ben Tarney
	 */
	private static void executeNOP(){
		incrementLC();
	}
	
	/**
	 * Divides c(ac) by the value specified by the operand. If the divisor is zero,
	 * halts execution. Otherwise, places the quotient in ac and the remainder in mq.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 05/30/09 - Ben Tarney<br>
	 * 		- Filled in method.<br><br>
	 * 	- 06/03/09 - Sam Jones<br>
	 * 		- Reworked to remove mathhelp() and make more readable.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Set mq to 0 at beginning.<br>
	 * 		- Fixed in case of immediate operand.<br>
	 * 		- Fixed to set ac = quotient and mq = remainder.<br>
	 * 		- Fixed documentation.<br>
	 * 		- Fixed overflow.
	 * @author Ben Tarney
	 */
	private static void executeDVH(BufferedWriter outputFile){
		mqRegister.setValue(0);
		int divisor;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			divisor = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			divisor = getEffAddress();
		}		
		
		if (divisor != 0) {
			// if there will be overflow as doing MIN_VALUE/-1
			if ((acRegister.getValue() == Integer.MIN_VALUE) && (divisor == -1)) {
				mqRegister.setValue(1);
				acRegister.setValue(-2);
			}
			else {
				int quotient = acRegister.getValue() / divisor;
				int remainder = acRegister.getValue() % divisor;
				acRegister.setValue(quotient);
				mqRegister.setValue(remainder);
			}
			incrementLC();
		} else {	// dividing by 0
			System.out.println("Division By Zero: Program Halted");
			executeHALT();
		}
	}
	
	/**
	 * Divides c(ac) by the value specified by the operand. If the divisor is zero,
	 * execution continues. Otherwise, places the quotient in ac and the remainder in mq.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	-5/30/09 - Ben Tarney<br>
	 * 		- Filled in method.<br><br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked to remove mathhelp() and make more readable.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Set mq to 0 at beginning.<br>
	 * 		- Fixed in case of immediate operand.<br>
	 * 		- Fixed to set ac = quotient and mq = remainder.<br>
	 * 		- Fixed documentation.<br>
	 * 		- Fixed overflow.
	 * @author Ben Tarney
	 */
	private static void executeDVP(BufferedWriter outputFile){
		mqRegister.setValue(0);
		int divisor;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			divisor = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			divisor = getEffAddress();
		}		
		
		if (divisor != 0) {
			// if there will be overflow as doing MIN_VALUE/-1
			if ((acRegister.getValue() == Integer.MIN_VALUE) && (divisor == -1)) {
				mqRegister.setValue(1);
				acRegister.setValue(-2);
			}
			else {
				int quotient = acRegister.getValue() / divisor;
				int remainder = acRegister.getValue() % divisor;
				acRegister.setValue(quotient);
				mqRegister.setValue(remainder);
			}
		}
		incrementLC();
	}
	
	/**
	 * Multiplies ac-mq by effective address and places it in ac/mq.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.<br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked to remove mathhelp() and make more readable.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>	
	 * 		- Clears mq at beginning.
	 * @author Ben Tarney
	 */
	private static void executeMPY(BufferedWriter outputFile){
		mqRegister.setValue(0);
		long value = 0;
		
		if (instructionRegister.getAddrFlag() != 2) {
			value = (long) acRegister.getValue() * (long) memory.getValue(getEffAddress());
		} else {
			value = (long) acRegister.getValue() * (long) getEffAddress();
		}
		if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
			long mqValue = (int) Long.rotateRight(value, 32);
			value = (int) value;

			if (mqValue == 0){
				mqRegister.setValue(1);
			}
			else {
				mqRegister.setValue((int) mqValue);
			}
			//acRegister.setValue(Integer.parseInt(acValue, 16));
		}
		else {
			acRegister.setValue((int)value);
		}
		acRegister.setValue((int)value);
		
		incrementLC();
	}
	
	/**
	 * Multiplies ac-mq by effective address and places it in ac/mq.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/30/09 - Ben Tarney<br>
	 * 		-Filled in method.<br><br>
	 * - 06/03/09 - Sam Jones<br>
	 * 		- reworked to remove mathhelp() and make more readable.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>	
	 * 		- Clears mq at beginning.
	 * @author Ben Tarney
	 */
	private static void executeMPR(BufferedWriter outputFile){
		mqRegister.setValue(0);
		long value = 0;
		
		if (instructionRegister.getAddrFlag() != 2) {
			value = acRegister.getValue() * memory.getValue(getEffAddress());
		} else {
			value = acRegister.getValue() * getEffAddress();
		}
		
		if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
			long mqValue = (int) Long.rotateRight(value, 32);
			value = (int) value;

			if (mqValue == 0){
				mqRegister.setValue(1);
			}
			else {
				mqRegister.setValue((int) mqValue);
			}
		}
		acRegister.setValue((int)value);
	
		incrementLC();
	}
	
	/**
	 * Transfers the address field of the current instruction into 
	 * the specified register.<br><br>
	 * 
	 * Change Log:<br>
	 * -5/27/09 - Dan Carpenter<br>
	 * - Filled in method.<br><br>
	 * -5/28/09 - Dan Carpenter<br>
	 * - Added overflow checking.<br><br>
	 * -6/1/09 - Dan Carpenter<br>
	 * - Added error reporting.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Fixed method to report the correct address.<br>
	 * 		- Added checking to make sure value will fit in xr.<br>
	 * 		- Added error reporting if address doesn't fit.
	 * @author Dan Carpenter
	 */
	private static void executeAXR(BufferedWriter outputFile){
		int address = getEffAddress();
		if (address > Short.MAX_VALUE) {
			xr1.setValue(Short.MAX_VALUE);
			try {
				outputFile.write("Error. Address too large for 16 bits. Replaced with max value.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.println("Problem writing to file.");
			}
		}
		else if (address < Short.MIN_VALUE) {
			xr1.setValue(Short.MIN_VALUE);
			try {
				outputFile.write("Error. Address too small for 16 bits. Replaced with min value.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.println("Problem writing to file.");
			}
		}
		else {
			xr1.setValue(getEffAddress());
		}
		incrementLC();
	}
	
	/**
	 * 	@author Dan Carpenter
	 *	Clears the accumulator and adds the value at the specified 
	 *	address to the accumulator.<br><br>
	 * 	Change Log:<br>
	 * 	- 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Changed method to be standardized when checking for immediate address.<br>
	 * 		- Sets mq to 0 initially.
	 */
	private static void executeCLA() {
		mqRegister.setValue(0);
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		acRegister.setValue(value);
		incrementLC();
	}
	
	

	/**
	 * @author Dan Carpenter
	 * 	Replaces the contents of the accumulator with the negative of the contents
	 * 	of memory at the specified address.<br><br>
	 * 
	 *	Change Log:<br>
	 * 	- 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Sets mq to 0 initially.<br>
	 * 		- Fixed overflow.
	 */
	private static void executeCLS() {
		mqRegister.setValue(0);
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		if (value == Integer.MIN_VALUE) {
			mqRegister.setValue(1);
			acRegister.setValue(-2);
		}
		else {
			acRegister.setValue(-value);
		}
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * Swaps the values in the AC register and the MQ register.<br><br>
	 * 
	 * Change Log:<br>
	 * - 5/27/09 - Dan Carpenter<br>
	 * - Filled in method body.<br>
	 */
	private static void executeXCA() {
		Register temp = new Register(WORD);
		temp = acRegister;
		acRegister = mqRegister;
		mqRegister = temp;
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * Retrieves the value at the specified address and places it in 
	 * the accumulator.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 05/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 06/03/09 - Sam Jones<br>
	 * 		- fixed calls to getEffAddr()
	 */
	private static void executeLD() {
		mqRegister.setValue(0);
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}

		acRegister.setValue(value);
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * 
	 * Loads xr1 with the decremented value at the specified location.<br><br>
	 * 
	 * Change Log:<br>
	 * - 5/29/09 - Dan Carpenter<br>
	 * - Filled in method body.<br><br>
	 * - 6/1/09 - Dan Carpenter<br>
	 * - Added error reporting.
	 * 
	 */
	private static void executeLXRD(BufferedWriter outputFile) {
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		value--;	// decrement
		
		if ((value > Short.MIN_VALUE) && (value < Short.MAX_VALUE)) {
			xr1.setValue(value);
		} else {
			xr1.setValue(value & Integer.parseInt("0000FFFF", 16));
		}
		incrementLC();
	}
	
	
	/**
	 * @author Dan Carpenter
	 * Copies the address field of the specified location in memory into index register 1<br><br>
	 * 
	 * Change Log:<br>
	 * - 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * - 6/1/09 - Dan Carpenter<br>
	 *		- Added error reporting.<br><br>
	 *	- 06/04/09 - Meghan Day<br>
	 *		- Fixed to get address of correct location.
	 */
	private static void executeLXRA(BufferedWriter outputFile) {
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}

		xr1.setValue(value & Integer.parseInt("0000FFFF", 16));
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * Copies the value at the specified address into the MQ register.<br><br>
	 * Change Log:<br>
	 * - 5/27/09 - Dan Carpenter<br>
	 * - Filled in method body.<br>
	 */
	private static void executeLDMQ() {
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		mqRegister.setValue(value);
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * 
	 * 	Puts the value at the given address into index register 1<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 5/29/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 6/1/09 - Dan Carpenter<br>
	 * 		- Added error reporting.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Changed bit arithmatic to be more intuitive.
	 */
	private static void executeLDX(BufferedWriter outputFile) {
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		if ((value > Short.MIN_VALUE) && (value < Short.MAX_VALUE)) {
			xr1.setValue(value);
		} else {
			xr1.setValue(value & Integer.parseInt("0000FFFF", 16));
		}
		incrementLC();
	}

	
	/**
	 * @author Dan Carpenter
	 * Moves the address field of the accumulator to index register 1.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 6/1/09 - Dan Carpenter<br>
	 * 		- Added error reporting.<br><br>
	 * 	- 6/2/09 - Dan Carpenter<br>
	 * 		- changed the method to take the low order 16 bits from the AC.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Implemented a much easier way.
	 */
	private static void executePAXR(BufferedWriter outputFile) {
		int value = acRegister.getAddressField();
		xr1.setValue(value);
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * The address portion of AC is replaced with the value of xr1.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 5/29/09 - Dan Carpenter<br>
	 * 		- Filled in method body<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Rewrote method and fixed description.
	 */
	private static void executePXR() {
		StringBuffer newValue = new StringBuffer(Integer.toHexString(acRegister.getValue()));
		StringBuffer xrValue = new StringBuffer(Integer.toHexString(xr1.getValue()));
		while (xrValue.length() < 4) {
			xrValue.insert(0, '0');
		}
		while (newValue.length() < 8) {
			newValue.insert(0, '0');
		}
		newValue.replace(4, 8, xrValue.toString());
		acRegister.setValue(Integer.parseInt(newValue.toString(), 16));
		incrementLC();
	}
	
	/**
	 * 	@author Dan Carpenter
	 * 	Stores the value in the accumulator at the specified address.<br><br>
	 * 	Change Log:<br>
	 * 	- 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br>
	 */
	private static void executeST() {
		memory.setValue(getEffAddress(), acRegister.getValue());
		incrementLC();	
	}
	
	/**
	 * @author Dan Carpenter
	 * This operation swaps the values in two specified registers.<br><br>
	 * 
	 * 	Change Log:<br>
	 * 	- 5/29/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Added checking xr numbers.<br><br
	 * 	- 06/05/09 - Meghan Day<br>
	 * 		- Fixed xr values after they're checked for array indexing.
	 */
	private static void executeEXR(BufferedWriter outputFile) {
		int[] registers = new int[7];
		registers[0] = xr1.getValue();
		registers[1] = xr2.getValue();
		registers[2] = xr3.getValue();
		registers[3] = xr4.getValue();
		registers[4] = xr5.getValue();
		registers[5] = xr6.getValue();
		registers[6] = xr7.getValue();
		
		int reg1 = instructionRegister.getAddressField();
		int reg2 = instructionRegister.getXR();
		
		if ((reg1 > 7) || (reg1 < 1) || (reg2 > 7) || (reg2 < 1)) {
			try {
			outputFile.write("Error. Index register number must be between 1 and 7.");
			outputFile.newLine();
			}
			catch (IOException ioe) {
			System.out.println("Problem writing to file.");
			}
		}
		else {
			reg1--;
			reg2--;		// adjust for array indexing
			int tempInt;
			tempInt = registers[reg1];
			registers[reg1] = registers[reg2];
			registers[reg2] = tempInt;
			
			xr1.setValue(registers[0]);
			xr2.setValue(registers[1]);
			xr3.setValue(registers[2]);
			xr4.setValue(registers[3]);
			xr5.setValue(registers[4]);
			xr6.setValue(registers[5]);
			xr7.setValue(registers[6]);
		}

		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * 	Stores the value in the MQ register at the specified address.<br><br>
	 * 	Change Log:<br>
	 * 	- 5/27/09 - Dan Carpenter<br>
	 * 		- Filled in method body.<br>
	 */
	private static void executeSTMQ() {
		memory.setValue(getEffAddress(), mqRegister.getValue());
		incrementLC();
	}
	
	/**
	 * @author Dan Carpenter
	 * Stores the value of the specified register at the 
	 * specified location in memory.<br><br>
	 * Change Log:<br>
	 * - 5/27/09 - Dan Carpenter<br>
	 * - Filled in method body.<br>
	 */
	private static void executeSTXR() {
		int address = getEffAddress();
		memory.setValue(address, xr1.getValue());
		incrementLC();
	}
	
	/** Replace the effadd in memory with zero.<br><br>
	 * @author Dan Carpenter
	 * 
	 * Change Log:<br>
	 * - 5/27/09 - Dan Carpenter<br>
	 * - Filled in method body.<br>
	 */
	private static void executeSTZ() {
		memory.setValue(getEffAddress(), 0);
		incrementLC();
	}
	
	/**
	 * Transfers to the specified address unconditionally.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTRA(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			locationCounter.setValue(address);
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}
	
	/**
	 * Transfers if the accumulator value is 0.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTACZ(BufferedWriter outputFile) {
		int address = getEffAddress();

		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (acRegister.getValue() == 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Sets index register 1 to the value of locationCounter + 1
	 * and transfers to the specified address unconditionally.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTSXR(BufferedWriter outputFile) {
		int address = getEffAddress();

		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			xr1.setValue(locationCounter.getValue() + 1);
			locationCounter.setValue(getEffAddress());
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Transfers to the specified address if the value of the accumulator
	 * is not negative.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTPL(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (acRegister.getValue() >= 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Transfers to the specified address if the value of the accumulator
	 * is not zero.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTNZ(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (acRegister.getValue() != 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}
	

	/**
	 * Transfers to the specified address if the value of index register 1
	 * is less than or equal to 0.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTXRL(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (xr1.getValue() <= 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Transfers to the specified address if the value of index register 1
	 * is greater than 0.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTXRP(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (xr1.getValue() > 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Transfers to the specified address if the result of the previous
	 * operation overflowed (i.e., if the value of the MQ is not 0).<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTMQO(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (mqRegister.getValue() != 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}

	/**
	 * Transfers to the specified address if the value of the MQ is positive.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Correct method so that it increments locationCounter if condition not true.<br><br>
	 * 	- 06/01/09 - Meghan Day<br>
	 * 		- Corrected method so that it makes sure address is within bounds.
	 */
	private static void executeTMQP(BufferedWriter outputFile) {
		int address = getEffAddress();
		if ((address >= loadAddress) && (address < loadAddress + moduleLen)) {
			if (mqRegister.getValue() > 0) {
				locationCounter.setValue(getEffAddress());
			}
			else {
				incrementLC();
			}
		}
		else {
			try {
				outputFile.write("Error. Address is outside the range of the program.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.print("Cannot write to file.");
			}
			incrementLC();
		}
	}
	
	/**
	 * Does a three-way transfer dependent on the value of ac and the location
	 * in memory. If c(ac) > c(mem(effadd)), the next instruction is executed.
	 * If c(ac) = c(mem(effadd)), the machine skips one instruction. If
	 * c(ac) < c(mem(effadd)), the machine skips two instructions.<br><br>
	 * Change log:<br>
	 * 	- 05/31/09 - Meghan Day<br>
	 * 		- Created skeleton.<br><br>
	 * 	- 06/02/09 - Meghan Day<br>
	 * 		- Filled in method.<br><br>
	 * 	- 06/04/09 - Meghan Day<br>
	 * 		- Fixed in case of immediate address.
	 */
	private static void executeCAS(BufferedWriter outputFile) {
		int value;
		
		// as long as address is not immediate, get value at returned address
		if (instructionRegister.getAddrFlag() != 2) {
			value = memory.getValue(getEffAddress());
		} else {	// if operand is immediate, just use the returned value
			value = getEffAddress();
		}
		
		if (acRegister.getValue() > value) {
			incrementLC();
		}
		else if (acRegister.getValue() == value) {
			incrementLC();
			incrementLC();
		}
		else {
			incrementLC();
			incrementLC();
			incrementLC();
		}
	}

	/**
	 * Depending on the value of the instruction register, dumps
	 * all registers, the contents of memory, or both.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote method.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Changed output destination to file.<br><br>
	 * 	- 06/02/09 - Meghan Day<br>
	 * 		- Cleaned up output.
	 */
	private static void executeDUMP(BufferedWriter outputFile) {
		int dumpFlag = instructionRegister.getAddressField();
		if ((dumpFlag == 1) || (dumpFlag == 3)) {
			// dump registers
			try {
				outputFile.write("AC:\t" + Integer.toHexString(acRegister.getValue()));
				outputFile.newLine();
				outputFile.write("MQ:\t" + Integer.toHexString(mqRegister.getValue()));
				outputFile.newLine();
				outputFile.write("LC:\t" + Integer.toHexString(locationCounter.getValue()));
				outputFile.newLine();
				outputFile.write("IR:\t" + Integer.toHexString(instructionRegister.getValue()));
				outputFile.newLine();
				outputFile.write("XR1:\t" + Integer.toHexString(xr1.getValue()));
				outputFile.newLine();
				outputFile.write("XR2:\t" + Integer.toHexString(xr2.getValue()));
				outputFile.newLine();
				outputFile.write("XR3:\t" + Integer.toHexString(xr3.getValue()));
				outputFile.newLine();
				outputFile.write("XR4:\t" + Integer.toHexString(xr4.getValue()));
				outputFile.newLine();
				outputFile.write("XR5:\t" + Integer.toHexString(xr5.getValue()));
				outputFile.newLine();
				outputFile.write("XR6:\t" + Integer.toHexString(xr6.getValue()));
				outputFile.newLine();
				outputFile.write("XR7:\t" + Integer.toHexString(xr7.getValue()));
				outputFile.newLine();
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.println("Cannot write to file.");
			}
		}
		if ((dumpFlag == 2) || (dumpFlag == 3)) {
			// dump memory
			dumpMemory(outputFile);
		}
		if ((dumpFlag > 3) || (dumpFlag < 1)) {
			try {
				outputFile.write("Error. DUMP operand must be 1, 2, or 3.");
				outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.println("Cannot write to file.");
			}
		}

		incrementLC();
	}

	/**
	 * Reads or writes integers or characters based on the value of
	 * the instruction register.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote skeleton.<br><br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Filled in method.<br><br>
	 * 	- 06/03/09 - Meghan Day<br>
	 * 		- Fixed to deal with char strings instead of single chars.
	 */
	private static void executeIOWD(BufferedWriter outputFile) {
		int iowdFlag = instructionRegister.getIOWDFlag();
		int address = getEffAddress();
		Scanner in = new Scanner(System.in);
		int value = 0, count = 0;
		char ch;
		
		switch (iowdFlag) {
		case 0: // read numeric
			System.out.print("Enter an integer: ");
			value = in.nextInt();
			memory.setValue(address, value);
			break;
		case 1: // read char
			System.out.print("Enter up to 4 characters: ");
			StringBuffer input = new StringBuffer(in.nextLine());
			count = 4;
			while (count > 0) {
				value *= 256;
				if (input.length() > 0) {
					ch = input.charAt(0);
					input.deleteCharAt(0);
				}
				else {
					ch = ' ';
				}
				value += (int)ch;
				count--;
			}
			memory.setValue(address, value);
			break;
		case 2: // write numeric
			System.out.println(memory.getValue(address));
			break;
		case 3: // write char
			StringBuffer output = new StringBuffer();
			value = memory.getValue(address);
			count = 4;
			while (count > 0) {
				ch = (char)(value % 256);
				value /= 256;
				output.insert(0, ch);
				count--;
			}
			System.out.println(output.toString());
			break;
		default:
			try {
			outputFile.write("Error. IOWD operand must be 0, 1, 2, or 3.");
			outputFile.newLine();
			}
			catch (IOException ioe) {
				System.out.println("Cannot write to file.");
			}
			break;
		}	

		incrementLC();
	}

	/**
	 * Stops execution.<br><br>
	 * Change log:<br>
	 * 	- 05/28/09 - Meghan Day<br>
	 * 		- Wrote skeleton.<br><br>
	 *  - 05/29/09 - Meghan Day<br>
	 *  	- Filled in method.
	 */
	private static void executeHALT() {
		locationCounter.setValue(loadAddress + moduleLen);
	}
	
	/**
	 * Dumps all the values in memory.<br><br>
	 * Change log:<br>
	 * - 05/23/09 - Meghan Day<br>
	 *  	- created initial skeleton for method.<br><br>
	 * - 05/27/09 - Sam Jones<br>
	 *  	- wrote method.<br><br>
	 * - 05/29/09 - Meghan Day<br>
	 * 		- added output to console in case of I/O error.<br><br>
	 * - 06/01/09 - Meghan Day<br>
	 * 		- Fixed method to increment count.<br><br>
	 * - 06/02/09 - Meghan Day<br>
	 * 		- Added leading 0's to values before writing to file.
	 */
	private static void dumpMemory(BufferedWriter outputFile){
		try {
			outputFile.write("MEM ADDR\tVALUE");
			outputFile.newLine();
			int count = 0;
			while (count <= MAX_MEM_ADDR) {
				if (Integer.toHexString(memory.getValue(count)).length() < 8) {
					StringBuffer hexString = new StringBuffer(Integer.toHexString(memory.getValue(count)));
					while (hexString.length() < 8) {
						hexString.insert(0, '0');
					}
					outputFile.write(Integer.toHexString(count) + "\t\t" + hexString.toString());
				}
				else {
					outputFile.write(Integer.toHexString(count) + "\t\t" + Integer.toHexString(memory.getValue(count)));
				}
				outputFile.newLine();
				count++;
			} 
			outputFile.newLine();
		}
		catch (IOException exception) {
			System.out.println("Cannot write to file.");
		}
	}
	
	/**
	 * 	Dumps the contents of all registers, the op-code of the current instruction,
	 * 	the address field, the effective address, and the binary version of the
	 * 	current instruction.<br><br>
	 * 	Change log:<br>
	 * 	- 05/23/09 - Meghan Day<br>
	 *  	- Created initial skeleton for method.<br><br>
	 *  - 05/27/09 - Sam Jones<br>
	 *  	- Wrote method.<br><Br>
	 * 	- 05/29/09 - Meghan Day<br>
	 * 		- Added output to console in case of I/O error.<br><br>
	 * 	- 06/02/09 - Meghan Day<br>
	 * 		- Rewrote so that output is lined up properly.<br>
	 * 		- Added code to fill in leading 0's.
	 */
	private static void dumpAfterInstruction(BufferedWriter outputFile){
		try {
			StringBuffer mqString = new StringBuffer(Integer.toHexString(mqRegister.getValue()));
			StringBuffer acString = new StringBuffer(Integer.toHexString(acRegister.getValue()));
			StringBuffer xr1String = new StringBuffer(Integer.toHexString(xr1.getValue()));
			StringBuffer xr2String = new StringBuffer(Integer.toHexString(xr2.getValue()));
			StringBuffer xr3String = new StringBuffer(Integer.toHexString(xr3.getValue()));
			StringBuffer xr4String = new StringBuffer(Integer.toHexString(xr4.getValue()));
			StringBuffer xr5String = new StringBuffer(Integer.toHexString(xr5.getValue()));
			StringBuffer xr6String = new StringBuffer(Integer.toHexString(xr6.getValue()));
			StringBuffer xr7String = new StringBuffer(Integer.toHexString(xr7.getValue()));
			StringBuffer lcString = new StringBuffer(Integer.toHexString(locationCounter.getValue()));
			StringBuffer irString = new StringBuffer(Integer.toHexString(instructionRegister.getValue()));
			StringBuffer irBinaryString = new StringBuffer(Integer.toBinaryString(instructionRegister.getValue()));
			StringBuffer opCodeString = new StringBuffer(Integer.toHexString(instructionRegister.getOpCode()));
			StringBuffer addrString = new StringBuffer(Integer.toHexString(instructionRegister.getAddressField()));
			StringBuffer effaddrString = new StringBuffer(Integer.toHexString(getEffAddress()));
			
			//fill with leading 0's
			while (mqString.length() < 8) {
				mqString.insert(0,'0');
			}
			while (acString.length() < 8) {
				acString.insert(0,'0');
			}
			while (irString.length() < 8) {
				irString.insert(0,'0');
			}
			while (xr1String.length() < 4) {
				xr1String.insert(0,'0');
			}
			while (xr2String.length() < 4) {
				xr2String.insert(0,'0');
			}
			while (xr3String.length() < 4) {
				xr3String.insert(0,'0');
			}
			while (xr4String.length() < 4) {
				xr4String.insert(0,'0');
			}
			while (xr5String.length() < 4) {
				xr5String.insert(0,'0');
			}
			while (xr6String.length() < 4) {
				xr6String.insert(0,'0');
			}
			while (xr7String.length() < 4) {
				xr7String.insert(0,'0');
			}
			while (lcString.length() < 4) {
				lcString.insert(0,'0');
			}
			while (irBinaryString.length() < 32) {
				irBinaryString.insert(0,'0');
			}
			while (opCodeString.length() < 2) {
				opCodeString.insert(0,'0');
			}
			while (addrString.length() < 4) {
				addrString.insert(0,'0');
			}
			while (effaddrString.length() < 4) {
				effaddrString.insert(0,'0');
			}
			
			outputFile.write("MQ: " + mqString.toString() + "\t\t");
			outputFile.write("XR2: " + xr2String.toString() + "\t\t");
			outputFile.write("XR5: " + xr5String.toString());
			outputFile.newLine();
			outputFile.write("AC: " + acString.toString() + "\t\t");
			outputFile.write("XR3: " + xr3String.toString() + "\t\t");
			outputFile.write("XR6: " + xr6String.toString());
			outputFile.newLine();
			outputFile.write("XR1: " + xr1String.toString() + "\t\t");
			outputFile.write("XR4: " + xr4String.toString() + "\t\t");
			outputFile.write("XR7: " + xr7String.toString());
			outputFile.newLine();
			outputFile.write("LC: " + lcString.toString() + "\t\t");
			outputFile.write("IR: " + irString.toString() + "\t\t");
			outputFile.write("IR in binary: " + irBinaryString.toString());
			outputFile.newLine();
			outputFile.write("Op-code: " + opCodeString.toString() + "\t\t");
			outputFile.write("Address: " + addrString.toString() + "\t\t");
			outputFile.write("Effadd: " + effaddrString.toString());
			outputFile.newLine();
			outputFile.newLine();
		} catch (IOException exception) {
			System.out.println("Cannot write to file.");
		}
	}
	
	/**
	 * Reads in and stores the information from the load file in memory while
	 * checking the information syntactically.<br><br>
	 * Change log:<br>
	 * - 05/23/09 - Meghan Day<br>
	 *  	- created initial skeleton for method.<br><Br>
	 * - 05/25/09 - Sam Jones<br>
	 * 		- wrote parse head record section of code.<br><Br>
	 * - 05/27/09 - Sam Jones<br>
	 * 		- fixed parse head record section of code.<br><Br>
	 *	- 05/28/09 - Meghan Day<br>
	 *		- Stored initial execution start address in locationCounter.<br><br>
	 *	- 06/02/09 - Meghan Day<br>
	 *		- Changed checking of version # and revision # in LH record.<br>
	 *		- Fixed overflow error in LT parsing.
	 */
	private static void pass1(BufferedReader sourceFile, BufferedWriter outputFile){
		Tokenizer tokenizer = new SimulatorTokenizer();
		String sourceLineBuffer;
		StringBuffer sourceLine = new StringBuffer();
		StringBuffer token = new StringBuffer();
		Assembler.TokenType[] type = {Assembler.TokenType.DATA};
		// booleans to keep track of whether head or end records have been parsed
		Boolean parsedHead = false, parsedEnd = false;
		
		// Keep count of number of records and compare this to number
		// in end record as part of error checking.
		int recordCount = 0;
		
		// Read in line from input until EOF
		try {
			sourceLineBuffer = sourceFile.readLine();
			while (sourceLineBuffer != null) {
				sourceLine = new StringBuffer(sourceLineBuffer);
				recordCount++;
				
				if (sourceLine.toString().length() > 0) {
					tokenizer.getNextToken(sourceLine, token, type);
					
					// Parse header record
					if (token.toString().compareTo("LH") == 0) {
						if (!parsedHead) {
							parsedHead = true;
							if (sourceLine.length() > 0) {
								tokenizer.getNextToken(sourceLine, token, type);
								moduleName = token.toString();
								if (sourceLine.length() > 0) {
									// remove start address
									tokenizer.getNextToken(sourceLine, token, type);
									try {
										locationCounter.setValue(Integer.parseInt(token.toString(), 16));
										if (locationCounter.getValue() > 4095) {
											locationCounter.setValue(4095);
										}
									}
									catch (NumberFormatException nfe1) {
										System.out.println("Error. Execution start address must be a valid hex integer.");
										locationCounter.setValue(0);
									}
									if (sourceLine.length() > 0) {
										// remove module length
										tokenizer.getNextToken(sourceLine, token, type);
										try {
											moduleLen = Integer.parseInt(token.toString(), 16);
											if (locationCounter.getValue() > 0) {
												moduleLen -= locationCounter.getValue();
											}
											if (locationCounter.getValue() + moduleLen > 4096) {
												System.out.println("Error. Execution start address + length cannot be greater than 4096.");
												moduleLen = 4096 - locationCounter.getValue();
											}
										} catch (NumberFormatException numberFormatException) {
											System.out.println("Error. Module length must be a valid hex integer.");
											moduleLen = 1;
										}
										if (sourceLine.length() > 0) {
											// remove load address
											tokenizer.getNextToken(sourceLine, token, type);
											try {
												loadAddress = Integer.parseInt(token.toString(), 16);
												if (loadAddress + moduleLen > 4096) {
													System.out.println("Error. Load address + length cannot be greater than 4096.");
													loadAddress = 4096 - moduleLen;
												}
											}
											catch (NumberFormatException nfe2) {
												System.out.println("Error. Load address must be a valid hex integer.");
											}
											if (sourceLine.length() > 0) {
												// remove date, check format
												tokenizer.getNextToken(sourceLine, token, type);
												try {
													if (token.toString().length() == 8) {
														Integer.parseInt(token.toString().substring(0, 4));
														Integer.parseInt(token.toString().substring(5));
														if (token.toString().charAt(4) != ':') {
															throw new NumberFormatException();
														}
													}
													else {
														throw new NumberFormatException();
													}
												} catch (NumberFormatException numberFormatException) {
													System.out.println("Error. Date is formatted incorrectly. Should be yyyy:ddd.");
												}
												if (sourceLine.length() > 0) {
													// remove time, check format
													tokenizer.getNextToken(sourceLine, token, type);
													try {
														if (token.toString().length() == 8){
															Integer.parseInt(token.toString().substring(0, 2));
															Integer.parseInt(token.toString().substring(3, 5));
															Integer.parseInt(token.toString().substring(6));
															if (token.toString().charAt(2) != ':' || token.toString().charAt(5) != ':') {
																throw new NumberFormatException();
															}
														}
														else {
															throw new NumberFormatException();
														}
													} catch (NumberFormatException numberFormatException) {
														System.out.println("Error. Time is formatted incorrectly. Should be hh:mm:ss.");
													}
													if (sourceLine.length() > 0) {
														tokenizer.getNextToken(sourceLine, token, type);
														if (token.toString().compareTo("CSE7000-LINK") == 0) {
															if (sourceLine.length() > 0) {
																// remove version #
																tokenizer.getNextToken(sourceLine, token, type);
																if (sourceLine.length() > 0) {
																	// remove revision #
																	tokenizer.getNextToken(sourceLine, token, type);
																} else {
																	System.out.println("Error. Incomplete header record.");
																}
															} else {
																System.out.println("Error. Incomplete header record.");
															}
														} else {
															// should read "CSE7000-LINK"
															System.out.println("Error. Should read \"CSE7000-LINK\".");
														}
													} else {
														System.out.println("Error. Incomplete header record.");
													}
												} else {
													System.out.println("Error. Incomplete header record.");
												}
											} else {
												System.out.println("Error. Incomplete header record.");
											}
										} else {
											System.out.println("Error. Incomplete header record.");
										}
									} else {
										System.out.println("Error. Incomplete header record.");
									}
								
								} else {
									System.out.println("Error. Incomplete header record.");
								}
							} else {
								System.out.println("Error. Incomplete header record");
							}
						} else {
							System.out.println("Error. Multiple header records.");
						}
					}
					
					// Parse text record
					else if (token.toString().compareTo("LT") == 0) {
						/* count text records
						 * compare to value from head record
						 * 
						 * check syntax for text records
						 */
						if (sourceLine.length() > 0) {
							tokenizer.getNextToken(sourceLine, token, type);
								
							try {
								//System.out.println("Load address: " + token.toString());
								int location = Integer.parseInt(token.toString(),16);
								if (location > 4095) {
									System.out.println("Error. Load address cannot be greater than 4095.");
									location = 4095;
								}

								if (sourceLine.length() > 0) {
									tokenizer.getNextToken(sourceLine, token, type);
									//System.out.println("Load value: " + token.toString());
									// token has code to be loaded
									try {
										int value = Integer.parseInt(token.toString(),16);
										if (Integer.toHexString(value).length() < 8) {
											StringBuffer hexString = new StringBuffer(Integer.toHexString(value));
											while (hexString.length() < 8) {
												hexString.insert(0, '0');
											}
											outputFile.write(Integer.toHexString(location) + ":\t" + hexString.toString());
										}
										else {
											outputFile.write(Integer.toHexString(location) + ":\t" + Integer.toHexString(value));
										}
										outputFile.newLine();
										memory.setValue(location, value);
									}
									catch (NumberFormatException nfe) {
										try {
											int value = (int)Long.parseLong(token.toString(),16);
											if (Integer.toHexString(value).length() < 8) {
												StringBuffer hexString = new StringBuffer(Integer.toHexString(value));
												while (hexString.length() < 8) {
													hexString.insert(0, '0');
												}
												outputFile.write(Integer.toHexString(location) + ":\t" + hexString.toString());
											}
											else {
												outputFile.write(Integer.toHexString(location) + ":\t" + Integer.toHexString(value));
											}
											outputFile.newLine();
											memory.setValue(location, value);
										}
										catch (NumberFormatException nfe2) {
											System.out.println("Error. Load value must be a valid hex integer.");
											memory.setValue(location, 1191182336); // NOP
										}
									}

									if (sourceLine.length() > 0) {
										tokenizer.getNextToken(sourceLine, token, type);
										// tokenizer has module name of source of code
									}
								}
								else{
									System.out.println("Error. Incomplete text record.");
								}
							}
							catch (NumberFormatException nfe) {
								System.out.println("Error. Instruction load address must be a valid hex integer.");
							}
						}
						else {
							System.out.println("Error. Incomplete text record.");
						}
					}

					// Parse end record
					else if (token.toString().compareTo("LE") == 0) {
						if (parsedEnd != true) {
							parsedEnd = true;
							outputFile.newLine();

							if (sourceLine.length()>0){
								tokenizer.getNextToken(sourceLine, token, type);
								try {
									if (Integer.parseInt(token.toString(), 16) != recordCount) {
										System.out.println("Error. Number of records not correct. Should be " + Integer.toHexString(recordCount));
									}
									else if (recordCount > 4098) {
										System.out.println("Error. Number of records is greater than 4098.");
									}
								}
								catch (NumberFormatException nfe) {
									System.out.println("Error. Number of records must be a valid hex integer.");
								}
							}
						}
						else {
							System.out.println("Error. Multiple end records.");
						}
					}
					else {
						System.out.println("Error. Line must begin with LH, LT, or LE.");
					}
				}
				sourceLineBuffer = sourceFile.readLine();
			}
		}
		catch (IOException IOE){
			System.out.println("Problem reading from file.");
		}
	}
	
	/**
	 *  Executes the program and outputs information.<br><br>
	 *  Change log:<br>
	 *  - 05/23/09 - Meghan Day<br>
	 *  	- created initial skeleton for method.<br><Br>
	 *  - 05/29/09 - Meghan Day<br>
	 *  	- Added switch statement and loop.<br><br>
	 *  - 06/03/09 - Meghan Day<br>
	 *  	- Added condition to while loop to make sure location counter is less than 4096.
	 */
	private static void pass2(BufferedWriter outputFile){
		while ((locationCounter.getValue() < (loadAddress + moduleLen)) && (locationCounter.getValue() < 4096)) {
			/*
			try {
				outputFile.write("Location counter: " + locationCounter.getValue());
				outputFile.newLine();
				outputFile.write("Load address: " + loadAddress);
				outputFile.newLine();
				outputFile.write("Module len: " + moduleLen);
				outputFile.newLine();
			}
			catch (IOException ioe) {
				
			}
			*/
			dumpAfterInstruction(outputFile);
			instructionRegister.setValue(memory.getValue(locationCounter.getValue()));
			int opCode = instructionRegister.getOpCode();
			
			switch (opCode) {
			case 81:
				executeABS();
				break;
			case 56:
				executeARS(outputFile);
				break;
			case 64:
				executeADD(outputFile);
				break;
			case 101:
				executeAXR(outputFile);
				break;
			case 48:
				executeANA();
				break;
			case 49:
				executeANS();
				break;
			case 102:
				executeBYRL(outputFile);
				break;
			case 103:
				executeBYRR(outputFile);
				break;
			case 122:
				executeCALL();
				break;
			case 78:
				executeCHS();
				break;
			case 75:
				executeCLA();
				break;
			case 76:
				executeCLS();
				break;
			case 121:
				executeCAS(outputFile);
				break;
			case 77:
				executeDRXR(outputFile);
				break;
			case 254:
				executeDUMP(outputFile);
				break;
			case 68:
				 executeDVH(outputFile);
				break;
			case 69:
				 executeDVP(outputFile);
				break;
			case 39:
				executeXCA();
				break;
			case 54:
				executeEORA();
				break;
			case 255:
				executeHALT();
				break;
			case 96:
				executeIOWD(outputFile);
				break;
			case 70:
				 executeINCXR(outputFile);
				break;
			case 55:
				executeALS(outputFile);
				break;
			case 0:
				executeLD();
				break;
			case 17:
				executeLXRD(outputFile);
				break;
			case 2:
				executeLDX(outputFile);
				break;
			case 16:
				executeLXRA(outputFile);
				break;
			case 1:
				executeLDMQ();
				break;
			case 57:
				executeLGSL(outputFile);
				break;
			case 51:
				executeLOR();
				break;
			case 53:
				executeLORS();
				break;
			case 58:
				executeLGLR(outputFile);
				break;
			case 72:
				 executeMOD();
				break;
			case 73:
				 executeMODQ();
				break;
			case 67:
				 executeMPY(outputFile);
				break;
			case 66:
				 executeMPR(outputFile);
				break;
			case 71:
				 executeNOP();
				break;
			case 50:
				executeOR();
				break;
			case 52:
				executeORS();
				break;
			case 38:
				executePAXR(outputFile);
				break;
			case 40:
				executePXR();
				break;
			case 74:
				executePWR(outputFile);
				break;
			case 80:
				executeSARZ();
				break;
			case 32:
				executeST();
				break;
			case 37:
				executeEXR(outputFile);
				break;
			case 36:
				executeSLW();
				break;
			case 33:
				executeSTMQ();
				break;
			case 34:
				executeSTXR();
				break;
			case 35:
				executeSTZ();
				break;
			case 65:
				executeSUB(outputFile);
				break;
			case 112:
				executeTRA(outputFile);
				break;
			case 114:
				executeTACZ(outputFile);
				break;
			case 118:
				executeTSXR(outputFile);
				break;
			case 117:
				executeTPL(outputFile);
				break;
			case 113:
				executeTNZ(outputFile);
				break;
			case 119:
				executeTXRL(outputFile);
				break;
			case 120:
				executeTXRP(outputFile);
				break;
			case 115:
				executeTMQO(outputFile);
				break;
			case 116:
				executeTMQP(outputFile);
				break;
			}
		}
		dumpAfterInstruction(outputFile);
	}
	
	
	/**
	 * 	Ran at execution from console.<br><br>
	 * 	Change log:<br>
	 * 	- 05/23/09 - Meghan Day<br>
	 *  	- Created initial skeleton for method.<br><Br>
	 *  - 06/01/09 - Meghan Day<br>
	 *  	- Fixed a few errors in checking names of input and output files.
	 *  @param args
	 */
	public static void main(String[] args){
		//Check arguments and initialize reader and writer
		final int NUMBER_OF_ARGS = 2;
    	
    	if(args.length >= NUMBER_OF_ARGS){
	        if(args[0].length() > 3){
			    if(args[0].substring(args[0].length() - 3).compareTo(".xe") == 0){
	                if(args[1].length() > 4){
	                    if(args[1].substring(args[1].length() - 4).compareTo(".txt") == 0){
		                    try{
	                    		File f = new File(args[0]);
	                    		if(f.exists()){
	                                BufferedReader sourceFile = new BufferedReader(new FileReader(args[0]));
	                                BufferedWriter outputFile = new BufferedWriter(new FileWriter(args[1]));
	                        		
	                        		pass1(sourceFile, outputFile);
	                                sourceFile.close();
	                        		//dumpMemory(outputFile);
	                        		pass2(outputFile);
	                        		dumpMemory(outputFile);
	                                outputFile.close();
	                                System.out.println("Simulator exited normally.");
	                                
	                    		}
	                    		else{
	                    			System.out.println("Error: Source file does not exist.");
	                    		}
		                    }
		                    catch(IOException ioe){
		                            System.out.println("Error: Problem initializing IO streams.");
		                    }
	                    }
	                    else{
	                            System.out.println("Error: Invalid output file name. File name must end in \".txt\".");
	                    }
	                }
	                else{
	                        System.out.println("Error: Output file name must be at least 5 characters long.");
	                }
		            }
		            else{
		                    System.out.println("Error: Invalid source file extension. File name must end in \".xe\".");
		            }
	        }
	        else{
	                System.out.println("Error: Source file name must be at least 4 characters long.");
	        }
    	}
    	else{
    		//if args.length < NUMBER_OF_ARGS
    		System.out.println("Error: Insufficient number of args. Simulator requires " + NUMBER_OF_ARGS + " to run properly.");
    	}
    	
	}
	
	/** 
	 * Gets the effective address of the current instruction.<br><br>
	 * Change Log:<br>
	 * - 05/27/09 - Sam Jones<br>
	 * 		- Created and wrote method.<br><br>
	 * - 06/04/09 - Meghan Day<br>
	 * 		- Fixed case of indirect when there is no index register.
	 * @param index Memory location to get address from.
	 * @return Effective address.
	 */
	private static int getEffAddress() {
		int effAddr = instructionRegister.getAddressField();
		if (instructionRegister.getAddrFlag() == 0) {
			if (instructionRegister.getXR() == 1) {
				effAddr += xr1.getValue();
			} else if (instructionRegister.getXR() == 2) {
				effAddr += xr2.getValue();
			} else if (instructionRegister.getXR() == 3) {
				effAddr += xr3.getValue();
			} else if (instructionRegister.getXR() == 4) {
				effAddr += xr4.getValue();
			} else if (instructionRegister.getXR() == 5) {
				effAddr += xr5.getValue();
			} else if (instructionRegister.getXR() == 6) {
				effAddr += xr6.getValue();
			} else if (instructionRegister.getXR() == 7) {
				effAddr += xr7.getValue();
			}
		} else if (instructionRegister.getAddrFlag() == 1) {
			if (instructionRegister.getXR() == 0) {
				effAddr = memory.getValue(effAddr);
			} else if (instructionRegister.getXR() == 1) {
				effAddr = memory.getValue(effAddr) + xr1.getValue();
			} else if (instructionRegister.getXR() == 2) {
				effAddr = memory.getValue(effAddr) + xr2.getValue();
			} else if (instructionRegister.getXR() == 3) {
				effAddr = memory.getValue(effAddr) + xr3.getValue();
			} else if (instructionRegister.getXR() == 4) {
				effAddr = memory.getValue(effAddr) + xr4.getValue();
			} else if (instructionRegister.getXR() == 5) {
				effAddr = memory.getValue(effAddr) + xr5.getValue();
			} else if (instructionRegister.getXR() == 6) {
				effAddr = memory.getValue(effAddr) + xr6.getValue();
			} else if (instructionRegister.getXR() == 7) {
				effAddr = memory.getValue(effAddr) + xr7.getValue();
			}
		}
		return effAddr;
	}
}
